/* eslint-disable no-console */
import { action, extendObservable } from 'mobx';
import _ from 'lodash';
import { message } from 'antd';
import { mixins } from './core';

function createDefaultActions(defaults = {}) {
  return {
    init() {
      extendObservable(this, defaults);
    },

    // store状态更新
    update: action(function (payload) {
      let obj = {};
      let arr = [];
      if (_.isArray(payload)) {
        payload.forEach((item) => {
          if (_.isString(item)) {
            arr.push(item);
          } else if (_.isObject(item)) {
            obj = { ...obj, ...item };
          }
        });
      } else if (_.isObject(payload)) {
        obj = { ...payload };
      }

      if (!_.isEmpty(obj)) {
        const keys = Object.keys(obj).filter((key) => _.has(this, key));
        keys.forEach((key) => {
          this[key] = obj[key];
        });
      }

      if (!_.isEmpty(arr)) {
        arr = arr.filter((key) => _.has(this, key));
        arr.forEach((key) => {
          this[key] = defaults[key];
        });
      }
    }),

    // store状态重置
    reset: action(function (payload) {
      const keys = (_.isString(payload)
        ? [payload]
        : _.isArray(payload)
          ? payload
          : []
      ).filter((item) => _.isString(item) && _.has(defaults, item));
      if (_.isEmpty(keys)) {
        Object.assign(this, _.cloneDeep(defaults));
      } else {
        keys.forEach((key) => {
          this[key] = defaults[key];
        });
      }
    })
  };
}

function createConfigActions(config = {}) {
  const res = {};
  (config.items || []).forEach((item) => {
    if (item.key === 'queryPaging') {
      res[item.key] = async function ({ query, sorter, pagination } = {}) {
        this.update({
          loading: true,
          query: { ...this.query, ...query },
          sorter: _.isEmpty(sorter) ? { ...this.sorter } : _.get(sorter, 'order') ? { ...sorter } : {},
          pagination: { ...this.pagination, ...pagination }
        });
        try {
          const params = { ...this.query };
          if (!_.isEmpty(this.pagination)) {
            params.pageNo = this.pagination.current;
            params.pageSize = this.pagination.pageSize;
          }
          if (!_.isEmpty(this.sorter)) {
            params.sortField = this.sorter.field;
            params.isAsc = this.sorter.order === 'ascend';
          }
          const data = await (item.caller || config.caller)[item.callee || item.key](params);
          this.update({
            loading: false,
            pagination: {
              ...this.pagination,
              total: _.get(data, 'total', 0)
            },
            dataSource: _.get(data, 'records', [])
          });
        } catch (error) {
          if (process.env.NODE_ENV === 'development') {
            console.error(error);
          }
        }
      };
    } else {
      res[item.key] = async function (params, done, fail) {
        try {
          const data = await (item.caller || config.caller)[item.callee || item.key](params);
          if (!_.isEmpty(item.map) && data !== null && typeof data !== 'undefined') {
            const payload = {};
            Object.keys(item.map).forEach((key) => {
              if (item.map[key] === 'data') {
                payload[key] = data;
              } else {
                payload[key] = _.get(data, item.map[key]);
              }
            });
            this.update(payload);
          }
          done?.(data);
        } catch (error) {
          fail?.(error);
          if (process.env.NODE_ENV === 'development') {
            console.error(error);
          }
          message.error(error.message);
        }
      };
    }
  });
  return res;
}

function merge(defaults, actions) {
  return function (target) {
    mixins({
      ...createDefaultActions(defaults),
      ...createConfigActions(actions)
    }, true)(target.prototype);
  };
}

function mergeTable(defaults, actions) {
  defaults = {
    // 列表加载状态
    loading: false,
    // 列表查询参数
    query: {},
    // 列表排序参数
    sorter: {},
    // 列表分页参数
    pagination: {

    },
    // 列表数据
    dataSource: [],

    ...defaults
  };
  return merge(defaults, actions);
}

function createStore(defaults, actions, methods) {
  function Store() {
    this.init();
  }
  merge(defaults, actions, methods)(Store);
  return new Store();
}

function createTableStore(defaults, actions, methods) {
  function Store() {
    this.init();
  }
  mergeTable(defaults, actions, methods)(Store);
  return new Store();
}

export {
  merge,
  mergeTable,
  createStore,
  createTableStore
};
